package com.czxy.util;

import com.czxy.vo.UserInfo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;

import java.security.PrivateKey;
import java.security.PublicKey;

/**
 * @author: XinQi.Yuan
 * @create: 2018-05-26 15:43
 **/
public class JwtUtils {
    /**
     * 私钥加密token
     *
     * @param userInfo      载荷中的数据
     * @param privateKey    私钥
     * @param expireMinutes 过期时间，单位秒
     * @return
     * @throws Exception
     */
    public static String generateToken(UserInfo userInfo, PrivateKey privateKey, int expireMinutes) throws Exception {
        return Jwts.builder()
                .claim(JwtConstans.JWT_KEY_ID, userInfo.getId())
                .claim(JwtConstans.JWT_KEY_USER_NAME, userInfo.getUsername())
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
                .signWith(SignatureAlgorithm.RS256, privateKey)
                .compact();
    }

    /**
     * 私钥加密token
     *
     * @param userInfo      载荷中的数据
     * @param privateKey    私钥字节数组
     * @param expireMinutes 过期时间，单位秒
     * @return
     * @throws Exception
     */
    public static String generateToken(UserInfo userInfo, byte[] privateKey, int expireMinutes) throws Exception {
        return Jwts.builder()
                .claim(JwtConstans.JWT_KEY_ID, userInfo.getId())
                .claim(JwtConstans.JWT_KEY_USER_NAME, userInfo.getUsername())
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
                .signWith(SignatureAlgorithm.RS256, RsaUtils.getPrivateKey(privateKey))
                .compact();
    }

    /**
     * 公钥解析token
     *
     * @param token     用户请求中的token
     * @param publicKey 公钥
     * @return
     * @throws Exception
     */
    private static Jws<Claims> parserToken(String token, PublicKey publicKey) {
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    }

    /**
     * 公钥解析token
     *
     * @param token     用户请求中的token
     * @param publicKey 公钥字节数组
     * @return
     * @throws Exception
     */
    private static Jws<Claims> parserToken(String token, byte[] publicKey) throws Exception {
        return Jwts.parser().setSigningKey(RsaUtils.getPublicKey(publicKey))
                .parseClaimsJws(token);
    }

    /**
     * 获取token中的用户信息
     *
     * @param token     用户请求中的令牌
     * @param publicKey 公钥
     * @return 用户信息
     * @throws Exception
     */
    public static UserInfo getInfoFromToken(String token, PublicKey publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        return new UserInfo(
                ObjectUtils.toInt(body.get(JwtConstans.JWT_KEY_ID)),
                ObjectUtils.toString(body.get(JwtConstans.JWT_KEY_USER_NAME))
        );
    }

    /**
     * 获取token中的用户信息
     *
     * @param token     用户请求中的令牌
     * @param publicKey 公钥
     * @return 用户信息
     * @throws Exception
     */
    public static UserInfo getInfoFromToken(String token, byte[] publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        return new UserInfo(
                        ObjectUtils.toInt(body.get(JwtConstans.JWT_KEY_ID)),
                        ObjectUtils.toString(body.get(JwtConstans.JWT_KEY_USER_NAME))
        );
    }

    /**
     * 测试jWTUtil
     */
    public static void main(String[] args) throws Exception {
        //1.公钥和私钥路径
        String pubKeyPath = "d:\\yxq\\rsa.pub";
        String priKeyPath = "d:\\yxq\\rsa.pri";
        //2.公钥和私钥对象
        PublicKey publicKey = RsaUtils.getPublicKey(pubKeyPath);
        PrivateKey privateKey = RsaUtils.getPrivateKey(priKeyPath);

        //3.userInfo
        UserInfo userInfo = new UserInfo(1001, "czxy");
        /****JWT用法： 私钥加密， 公钥解密******/
//        String token = JwtUtils.generateToken(userInfo, privateKey, 30);
//
//        System.out.println(token);

        /********公钥解密*************/
        String token="eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MTAwMSwidXNlcm5hbWUiOiJjenh5IiwiZXhwIjoxNTQ1MDk0NjMyfQ.gxY1qqxEkAJe12U45ale-bn8uLcm0qOMTgpqF2Fjj3M0R8fw5sozs5SKMRX0QFlVoHR34R83rU2TzPsLW9WBpgNQpvLPj_oV1rXsn1oh5XuuR5TBGS2VQnWGGtR5USaUrRSaGvZonhYQ247bULFOt7h5K16XxLfvljmuPzRXfWA";

        Jws<Claims> claimsJws = JwtUtils.parserToken(token, publicKey);
        System.out.println(claimsJws);
    }
}